﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using br.com.SistemaChamados.QueryManager.ReaderParser;
using br.com.SistemaChamados.QueryManager.Core.Behavior;
using br.com.SistemaChamados.QueryManager.Enum;
using br.com.SistemaChamados.QueryManager.Utils;
using QueryManager.Core;

namespace br.com.SistemaChamados.QueryManager.Core
{
    public sealed class QueryManagerPerformer
    {

        public static List<object> Select(Type _typeClass, ConnectionBehavior behavior)
        {
            List<object> result = new List<object>();
            IDbConnection _conn = Mapped.Connection();
            string _sql = QueryManagerStatementConstructor.buildASelectSql(_typeClass);
            IDbCommand _command = Mapped.Command(_sql, _conn);
            IDataReader _reader = _command.ExecuteReader((CommandBehavior)ConnectionBehavior.CONNECTION_BEHAVIOR_CLOSE_AFTER_OPERATION);
            DataParser parser = new DataParser(_typeClass, _reader);
            result = parser.processAndConvertIDataReader();
            closeConnection(_conn);
            return result;
        }

        public static object Select(Type _typeClass, string fieldIdentifier, object valueIdentifier, ConnectionBehavior behavior)
        {
            List<object> result = new List<object>();
            IDbConnection _conn = Mapped.Connection();//TODO: verificar se não é melhor construir uma ConnectionFactory
            string tableFieldIdentifier = QueryManagerConstants.PREFIX_FIELD + _typeClass.Name + fieldIdentifier;
            string _sql = QueryManagerStatementConstructor.buildASelectSql(_typeClass, tableFieldIdentifier, valueIdentifier);
            IDbCommand _command = Mapped.Command(_sql, _conn);
            IDataReader _reader = _command.ExecuteReader((CommandBehavior)ConnectionBehavior.CONNECTION_BEHAVIOR_CLOSE_AFTER_OPERATION);
            DataParser parser = new DataParser(_typeClass, _reader);
            result = parser.processAndConvertIDataReader();
            closeConnection(_conn);
            if (result != null && result.Count > 0)
            {
                return result[0];
            }
            else
            {
                return null;
            }
        }

        public static EnumCRUDState Insert(object insertableObject, string[] propertiesExceptionInsert, ConnectionBehavior behavior)
        {
            EnumCRUDState stateOperation = EnumCRUDState.SQL_NOTHING;
            IDbConnection _conn = null;
            try
            {
                _conn = Mapped.Connection();
                string aSql = QueryManagerStatementConstructor.buildAnInsertSql(insertableObject, propertiesExceptionInsert);
                stateOperation = executeDMLCommand(_conn, aSql);
            }
            catch (Exception ex)
            {
                stateOperation = EnumCRUDState.SQL_ERROR;
                throw ex;
            }
            finally
            {
                closeConnection(_conn);
            }
            return stateOperation;
        }

        public static EnumCRUDState Update(object updatableObject, string fieldIdentifier, object identifier, ConnectionBehavior behavior)
        {
            EnumCRUDState stateOperation = EnumCRUDState.SQL_NOTHING;
            IDbConnection _conn = null;
            try
            {
                _conn = Mapped.Connection();
                string aSql = QueryManagerStatementConstructor.buildAUpdateSql(updatableObject, fieldIdentifier, identifier);
                stateOperation = executeDMLCommand(_conn, aSql);
            }
            catch (Exception ex)
            {
                stateOperation = EnumCRUDState.SQL_ERROR;
                throw ex;
            }
            finally
            {
                closeConnection(_conn);
            }
            return stateOperation;
        }

        public static EnumCRUDState Delete(object deletableObject, ConnectionBehavior behavior)
        {
            EnumCRUDState stateOperation = EnumCRUDState.SQL_NOTHING;
            IDbConnection _conn = null;
            try
            {
                _conn = Mapped.Connection();
                string aSql = QueryManagerStatementConstructor.buildADeleteSql(deletableObject);
                stateOperation = executeDMLCommand(_conn, aSql);
            }
            catch (Exception ex)
            {
                stateOperation = EnumCRUDState.SQL_ERROR;
                throw ex;
            }
            finally
            {
                closeConnection(_conn);
            }
            return stateOperation;
        }

        private static EnumCRUDState executeDMLCommand(IDbConnection _conn, string aSql)
        {
            EnumCRUDState state = EnumCRUDState.SQL_NOTHING;
            try
            {
                IDbCommand command = Mapped.Command(aSql, _conn);
                command.ExecuteNonQuery();
                state = EnumCRUDState.SQL_SUCCESS;
            }
            catch (Exception ex)
            {
                state = EnumCRUDState.SQL_ERROR;
                throw ex;
            }
            return state;
        }

        private static void closeConnection(IDbConnection conn)
        {
            try
            {
                if (conn != null) conn.Close();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

    }
}